home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / terminal / qterm-6.0 / qterm-6 / options.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-12  |  10.8 KB  |  470 lines

  1. /*
  2.  * Copyright (c) 1990 Michael A. Cooper.
  3.  * This software may be freely distributed provided it is not sold for 
  4.  * profit and the author is credited appropriately.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *RCSid = "$Header: /src/common/usc/lib/libgen/RCS/options.c,v 1.15 1992/11/12 19:11:26 mcooper Exp $";
  9. #endif
  10.  
  11. /*
  12.  * $Log: options.c,v $
  13.  * Revision 1.15  1992/11/12  19:11:26  mcooper
  14.  * Fix declaration of UsageString().
  15.  *
  16.  * Revision 1.14  1992/04/16  01:28:02  mcooper
  17.  * Some de-linting.
  18.  *
  19.  * Revision 1.13  1990/12/15  18:13:28  mcooper
  20.  * Add copywrite notice.
  21.  *
  22.  * Revision 1.12  90/12/15  17:51:46  mcooper
  23.  * Add #ifdef HAS_VARARGS around include for <varargs>.
  24.  * 
  25.  * Revision 1.11  90/11/13  16:39:28  mcooper
  26.  * Add #ifdef HAS_VARARGS for systems without
  27.  * varargs.
  28.  * 
  29.  * Revision 1.10  90/11/13  15:28:01  mcooper
  30.  * - Add OptBool cvtarg routine.
  31.  * - Print default values in HelpOptions() 
  32.  *   when appropriate.
  33.  * 
  34.  * Revision 1.9  90/11/13  15:19:00  mcooper
  35.  * Added supported for options being both
  36.  * SepArg and StickyArg.
  37.  * 
  38.  * Revision 1.8  90/10/30  21:02:31  mcooper
  39.  * Need to exit() if -help is specified.
  40.  * 
  41.  * Revision 1.7  90/10/30  20:24:33  mcooper
  42.  * Fixed bug in UsageString().
  43.  * 
  44.  * Revision 1.6  90/10/30  19:53:05  mcooper
  45.  * Cleaned up some NeXT cc and lint stuff.
  46.  * 
  47.  * Revision 1.5  90/10/30  19:45:31  mcooper
  48.  * Remove unneeded paramter to HelpOptions().
  49.  * 
  50.  * Revision 1.4  90/10/29  14:47:42  mcooper
  51.  * Added real function UsageString() to
  52.  * handle formating usage option strings.
  53.  * 
  54.  * Revision 1.3  90/10/29  14:17:00  mcooper
  55.  * Allow options to be abbreviated 
  56.  * (for all non StickArg options).
  57.  * 
  58.  * Revision 1.2  90/10/26  15:56:11  mcooper
  59.  * - Fix bug in SepArg code that ate arguments.
  60.  * - Cleanup help message.
  61.  * - Add ArgHidden code.
  62.  * 
  63.  * Revision 1.1  90/10/26  14:42:51  mcooper
  64.  * Initial revision
  65.  * 
  66.  */
  67.  
  68. /*
  69.  * Functions to parse options.
  70.  */
  71.  
  72. #include "options.h"
  73. #ifdef HAS_VARARGS
  74. #include <varargs.h>
  75. #endif
  76.  
  77. char *OptionChars = "-+";    /* Default option switching characters */
  78. char *ProgramName = NULL;    /* Name of this program */
  79. static char *UsageString();
  80. static int isopt();
  81. static int suppress_help_msg = 0;
  82. char *strcat();
  83.  
  84. /*
  85.  * ParseOptions - Parse options found in argv using "options".
  86.  *          Returns the number of options parsed if there
  87.  *          were no errors.  Returns -1 if an error occurs.
  88.  */
  89. int ParseOptions(options, num_options, argc, argv)
  90.      OptionDescRec *options;
  91.      int num_options;
  92.      int argc;
  93.      char **argv;
  94. {
  95.     OptionDescRec *opt;
  96.     register int x;
  97.     char *p;
  98.  
  99.     if (ProgramName == NULL)
  100.     ProgramName = argv[0];
  101.  
  102. #ifdef OPTION_DEBUG
  103.     (void) printf("Option list is:\n");
  104.     for (x = 0; x < num_options; ++x) {
  105.     opt = &options[x];
  106.     (void) printf("%s\n", opt->option);
  107.     }
  108.  
  109.     (void) printf("Arguments (%d):", argc);
  110.     for (x = 0; x < argc; ++x) {
  111.     (void) printf(" %s", argv[x]);
  112.     }
  113.     (void) printf("\n");
  114. #endif /* OPTION_DEBUG */
  115.  
  116.     for (x = 1; x < argc; ++x) {
  117.     if (strcmp(HELPSTR, argv[x]) == 0) {
  118.         HelpOptions(options, num_options, (char **)NULL);
  119.         exit(0);
  120.     }
  121.  
  122.     opt = FindOption(options, num_options, argv[x]);
  123.     if (opt == NULL) {
  124.         if (isopt(argv[x])) { /* this was suppose to be an option */
  125.         UsageOptions(options, num_options, argv[x]);
  126.         return(-1);
  127.         } else { /* must be end of options */
  128.         break;
  129.         }
  130.     }
  131.  
  132.     if (opt->flags & NoArg) {
  133.         if (!(*opt->cvtarg)(opt, opt->value, FALSE)) {
  134.         UsageOptions(options, num_options, opt->option);
  135.         return(-1);
  136.         }
  137.     } else if (opt->flags & IsArg) {
  138.         if (!(*opt->cvtarg)(opt, opt->option, FALSE)) {
  139.         UsageOptions(options, num_options, opt->option);
  140.         return(-1);
  141.         }
  142.     } else if ((opt->flags & StickyArg) && (opt->flags & SepArg)) {
  143.         p = (char *) &argv[x][strlen(opt->option)];
  144.         if (!*p) {        /*** SepArg ***/
  145.         if (x + 1 >= argc || isopt(argv[x+1])) {
  146.             if (opt->value == (caddr_t) NULL) {
  147.             UserError("%s: Option requires an argument.", argv[x]);
  148.             UsageOptions(options, num_options, opt->option);
  149.             return(-1);
  150.             }
  151.             p = opt->value;
  152.         } else {
  153.             p = argv[++x];
  154.         }
  155.         }
  156.         if (!(*opt->cvtarg)(opt, p, TRUE)) {
  157.         UsageOptions(options, num_options, opt->option);
  158.         return(-1);
  159.         }
  160.     } else if (opt->flags & StickyArg) {
  161.         p = (char *) &argv[x][strlen(opt->option)];
  162.         if (!*p) {
  163.         if (opt->value == (caddr_t) NULL) {
  164.             UserError("%s: Option requires an argument.", argv[x]);
  165.             UsageOptions(options, num_options, opt->option);
  166.             return(-1);
  167.         } else {
  168.             p = opt->value;
  169.         }
  170.         }
  171.         if (!(*opt->cvtarg)(opt, p, TRUE)) {
  172.         UsageOptions(options, num_options, opt->option);
  173.         return(-1);
  174.         }
  175.     } else if (opt->flags & SepArg) {
  176.         if (x + 1 >= argc || isopt(argv[x+1])) {
  177.         if (opt->value == (caddr_t) NULL) {
  178.             UserError("%s: Option requires an argument.", argv[x]);
  179.             UsageOptions(options, num_options, opt->option);
  180.             return(-1);
  181.         } else {
  182.             p = opt->value;
  183.         }
  184.         } else {
  185.         p = argv[++x];
  186.         }
  187.         if (!(*opt->cvtarg)(opt, p, TRUE)) {
  188.         UsageOptions(options, num_options, opt->option);
  189.         return(-1);
  190.         }
  191.     } else if (opt->flags & SkipArg) {
  192.         x += 2;
  193.     } else if (opt->flags & SkipLine) {
  194.         return(x);
  195.     } else if (opt->flags & SkipNArgs) {
  196.         if (opt->value) {
  197.         x += atoi(opt->value);
  198.         } else {
  199.         UserError("Internal Error: No 'value' set for SkipNArgs.");
  200.         return(-1);
  201.         }
  202.     } else {
  203.         UserError("Internal Error: Unknown argument type for option '%s'.",
  204.              opt->option);
  205.         return(-1);
  206.     }
  207.     }
  208.  
  209.     return(x);
  210. }
  211.  
  212. /*
  213.  * FindOption - Find "option" in "options".  Returns NULL if not found.
  214.  */
  215. OptionDescRec *FindOption(options, num_options, option)
  216.      OptionDescRec *options;
  217.      int num_options;
  218.      char *option;
  219. {
  220.     OptionDescRec *opt;
  221.     register int x;
  222.  
  223.     for (x = 0; x < num_options; ++x) {
  224.     opt = &options[x];
  225.     if (opt->flags & StickyArg) {
  226.         if (strncmp(option, opt->option, strlen(opt->option)) == 0)
  227.         return(opt);
  228.     } else {
  229.         if (strncmp(option, opt->option, strlen(option)) == 0)
  230.         return(opt);
  231.     }
  232.     }
  233.  
  234.     return(NULL);
  235. }
  236.  
  237. /*
  238.  * isopt - Is "str" an option string?  Compare first char of str against
  239.  *       list of option switch characters.  Returns TRUE if it is an option.
  240.  */
  241. static int isopt(str)
  242.      char *str;
  243. {
  244.     register char *p;
  245.  
  246.     for (p = OptionChars; p && *p; ++p) {
  247.     if (*str == *p) {
  248.         return(TRUE);
  249.     }
  250.     }
  251.  
  252.     return(FALSE);
  253. }
  254.  
  255. /*
  256.  * UsageOptions - Print a usage message based on "options".
  257.  */
  258. void UsageOptions(options, num_opts, badOption)
  259.      OptionDescRec *options;
  260.      int num_opts;
  261.      char *badOption;
  262. {
  263.     OptionDescRec *opt;
  264.     char *optstr;
  265.     register int x;
  266.     int col, len;
  267.  
  268.     if (badOption) 
  269.     (void) fprintf (stderr, "%s:  bad command line option \"%s\"\r\n\n",
  270.             ProgramName, badOption);
  271.  
  272.     (void) fprintf (stderr, "usage:  %s", ProgramName);
  273.     col = 8 + strlen(ProgramName);
  274.     for (x = 0; x < num_opts; x++) {
  275.     opt = &options[x];
  276.     if (opt->flags & ArgHidden)
  277.         continue;
  278.     optstr = UsageString(opt);
  279.     len = strlen(optstr) + 3;    /* space [ string ] */
  280.     if (col + len > 79) {
  281.         (void) fprintf (stderr, "\r\n   ");  /* 3 spaces */
  282.         col = 3;
  283.     }
  284.     (void) fprintf (stderr, " [%s]", optstr);
  285.     col += len;
  286.     }
  287.  
  288.     if (suppress_help_msg)
  289.     (void) fprintf(stderr, "\r\n\n");
  290.     else
  291.     (void) fprintf(stderr, 
  292.                "\r\n\nType \"%s %s\" for a full description.\r\n\n",
  293.                ProgramName, HELPSTR);
  294. }
  295.  
  296. /*
  297.  * HelpOptions - Print a nice help/usage message based on options.
  298.  */
  299. void HelpOptions(options, num_opts, message)
  300.      OptionDescRec *options;
  301.      int num_opts;
  302.      char **message;
  303. {
  304.     OptionDescRec *opt;
  305.     register int x;
  306.     char **cpp;
  307.  
  308.     suppress_help_msg = 1;
  309.     UsageOptions(options, num_opts, (char *)NULL);
  310.     suppress_help_msg = 0;
  311.  
  312.     (void) fprintf (stderr, "where options include:\n");
  313.     for (x = 0; x < num_opts; x++) {
  314.     opt = &options[x];
  315.     if (opt->flags & ArgHidden)
  316.         continue;
  317.     (void) fprintf (stderr, "    %-28s %s\n", UsageString(opt), 
  318.          (opt->desc) ? opt->desc : "");
  319.     if (opt->value && opt->cvtarg != OptBool)
  320.         (void) fprintf (stderr, "    %-28s [ Default value is %s ]\n", 
  321.                 "", opt->value);
  322.     }
  323.  
  324.     if (message) {
  325.     (void) putc ('\n', stderr);
  326.     for (cpp = message; *cpp; cpp++) {
  327.         (void) fputs (*cpp, stderr);
  328.         (void) putc ('\n', stderr);
  329.     }
  330.     (void) putc ('\n', stderr);
  331.     }
  332. }
  333.  
  334. /*
  335.  * UserError - Print a user error.
  336.  */
  337. #ifdef HAS_VARARGS
  338. void UserError(va_alist)
  339.      va_dcl
  340. {
  341.     va_list args;
  342.     char *fmt;
  343.  
  344.     va_start(args);
  345.     if (ProgramName)
  346.     (void) fprintf(stderr, "%s: ", ProgramName);
  347.     fmt = (char *) va_arg(args, char *);
  348.     (void) vfprintf(stderr, fmt, args);
  349.     va_end(args);
  350.     (void) fprintf(stderr, "\n");
  351. }
  352. #else
  353. void UserError(fmt, a1, a2, a3, a4, a5, a6)
  354.      char *fmt;
  355. {
  356.     if (ProgramName)
  357.     (void) fprintf(stderr, "%s: ", ProgramName);
  358.     (void) fprintf(stderr, fmt, a1, a2, a3, a4, a5, a6);
  359.     (void) fprintf(stderr, "\n");
  360. }
  361. #endif
  362.  
  363. OptBool(opt, value, docopy)
  364.      OptionDescRec *opt;
  365.      caddr_t value;
  366.      int docopy; /*ARGSUSED*/
  367. {
  368.     char *vpp;
  369.  
  370.     *(int *) opt->valp = (int) strtol(value, &vpp, 0);
  371.     if (*vpp) {
  372.     UserError("Invalid integer argument for '%s'.", opt->option);
  373.     return(FALSE);
  374.     } else {
  375.     return(TRUE);
  376.     }
  377. }
  378.  
  379. OptInt(opt, value, docopy)
  380.      OptionDescRec *opt;
  381.      caddr_t value;
  382.      int docopy; /*ARGSUSED*/
  383. {
  384.     char *vpp;
  385.  
  386.     *(int *) opt->valp = (int) strtol(value, &vpp, 0);
  387.     if (*vpp) {
  388.     UserError("Invalid integer argument for '%s'.", opt->option);
  389.     return(FALSE);
  390.     } else {
  391.     return(TRUE);
  392.     }
  393. }
  394.  
  395. OptShort(opt, value, docopy)
  396.      OptionDescRec *opt;
  397.      caddr_t value;
  398.      int docopy; /*ARGSUSED*/
  399. {
  400.     char *vpp;
  401.  
  402.     *(short *) opt->valp = (short) strtol(value, &vpp, 0);
  403.     if (*vpp) {
  404.     UserError("Invalid integer argument for '%s'.", opt->option);
  405.     return(FALSE);
  406.     } else {
  407.     return(TRUE);
  408.     }
  409. }
  410.  
  411. OptLong(opt, value, docopy)
  412.      OptionDescRec *opt;
  413.      caddr_t value;
  414.      int docopy; /*ARGSUSED*/
  415. {
  416.     char *vpp;
  417.  
  418.     *(long *) opt->valp = (long) strtol(value, &vpp, 0);
  419.     if (*vpp) {
  420.     UserError("Invalid integer argument for '%s'.", opt->option);
  421.     return(FALSE);
  422.     } else {
  423.     return(TRUE);
  424.     }
  425. }
  426.  
  427. OptStr(opt, value, docopy)
  428.      OptionDescRec *opt;
  429.      caddr_t value;
  430.      int docopy;
  431. {
  432.     char *p;
  433.  
  434.     if (docopy) {
  435.     if ((p = (char *) malloc((unsigned)strlen(value)+1)) == NULL) {
  436.         UserError("Cannot malloc memory: %s", SYSERR);
  437.         return(FALSE);
  438.     }
  439.     (void) strcpy(p, value);
  440.     } else {
  441.     p = value;
  442.     }
  443.  
  444.     *(char **) opt->valp = p;
  445.  
  446.     return(TRUE);
  447. }
  448.  
  449. static char *UsageString(opt)
  450.      OptionDescRec *opt;
  451. {
  452.     static char buf[BUFSIZ], buf2[BUFSIZ];
  453.  
  454.     (void) sprintf(buf, opt->option);
  455.     (void) strcpy(buf2, "");
  456.     if (opt->usage) {
  457.     (void) sprintf(buf2, "%s%s%s%s",
  458.                ((opt->flags & StickyArg) && 
  459.             !((opt->flags & StickyArg) && (opt->flags & SepArg))) 
  460.                ? "" : " ",
  461.                (opt->value) ? "[" : "",
  462.                opt->usage,
  463.                (opt->value) ? "]" : ""
  464.                );
  465.     }
  466.     (void) strcat(buf, buf2);
  467.  
  468.     return(buf);
  469. }
  470.